package services

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strconv"

	"cashew.com/cashew_common/configs"
	"cashew.com/cashew_common/utils"
	"cashew.com/cashew_task/dtos"
	"github.com/beego/beego/v2/core/logs"
	"github.com/pkg/errors"
)

/*
type ExceptionUserHandling struct {
}
*/
/*
func (e *ExceptionUserHandling) Run(mainWg *sync.WaitGroup) {
	mainWg.Add(1)

	go func() {
		exeptionHandlerTicker := time.NewTicker(constants.EXCEPTION_USER_HANDLING_TIMEING)
		for {
			select {
			case <-exeptionHandlerTicker.C:
				logs.Info("Run::exception user handling start::time:", time.Now().Format("2006-01-02 15:04:05"))
				e.exceptionHandling()
			}
		}
		mainWg.Done()
	}()

}
*/

func ExceptionHandling() error {
	uHandleErr := exceptionUserHandling()
	if uHandleErr != nil {
		return uHandleErr
	}

	aHandleErr := exceptionAnchorHandling()
	if aHandleErr != nil {
		return aHandleErr
	}
	return nil
}

// 处理用户
func exceptionUserHandling() error {
	db := utils.GetDB()
	if db == nil {
		return errors.New("exceptionUserHandling db is nil")
	}
	rows, queryErr := db.Query("SELECT user_id, gender FROM users WHERE status <> 1 AND update_time < UNIX_TIMESTAMP(NOW() - INTERVAL 2 MINUTE )")
	if queryErr != nil {
		logs.Error("exceptionUserHandling::exception user handling failed::query error:", queryErr)
		return queryErr
	}
	defer rows.Close()

	for rows.Next() {
		var (
			userId int64 = 0
			gender       = 1
		)
		scanErr := rows.Scan(&userId, &gender)
		if scanErr == nil {
			userDisconnect(userId, gender)
		}
	}
	return nil
}

// 处理主播
func exceptionAnchorHandling() error {
	db := utils.GetDB()
	if db == nil {
		return errors.New("exceptionAnchorHandling db is nil")
	}
	rows, queryErr := db.Query("SELECT anchor_id FROM anchor_info WHERE status <> 1 AND active_time < UNIX_TIMESTAMP(NOW() - INTERVAL 2 MINUTE )")
	if queryErr != nil {
		logs.Error("exceptionAnchorHandling::exception anchor handling failed::query error:", queryErr)
		return queryErr
	}
	defer rows.Close()

	for rows.Next() {
		var (
			anchorId int64 = 0
		)
		scanErr := rows.Scan(&anchorId)
		if scanErr == nil {
			uDiscError := userDisconnect(anchorId, 2)
			if uDiscError != nil {
				logs.Error("exceptionAnchorHandling::exception anchor handling failed::user disconnect error:", uDiscError)
				return uDiscError
			}
		}
	}
	return nil
}

func userDisconnect(userid int64, gender int) error {

	httpClient := &http.Client{}
	uDisconnect := dtos.UserDisconnect{
		UserId: strconv.FormatInt(userid, 10),
		Gender: gender,
	}

	jsonWsOff, jsonErr := json.Marshal(uDisconnect)
	if jsonErr != nil {
		logs.Error("userDisconnect::user disconnect json marshal failed:", jsonErr, " user id:", userid)
		return jsonErr
	}

	bodyReader := bytes.NewReader(jsonWsOff)

	request, err := http.NewRequest(http.MethodPost, configs.OffUrl, bodyReader)
	if err != nil {
		logs.Error("userDisconnect::user disconnect request failed:", err, " user id:", userid)
		return err
	}

	request.Header.Set("Content-Type", "application/json")
	resp, respErr := httpClient.Do(request)
	if respErr != nil {
		logs.Error("userDisconnect::user disconnect response failed:", respErr, " user id:", userid)
		return respErr
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logs.Error("userDisconnect::user disconnect read response failed:", err, " user id:", userid)
		return err
	}

	defer resp.Body.Close()

	logs.Info("userDisconnect::user disconnect success::user id:", userid, " gender:", gender, " response:", string(body))
	return nil
}
